package com.jirefox.loner.runtime.controller;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.HandlerMapping;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jirefox.loner.runtime.service.SqlHolder;

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

@RestController
public class ScriptExecutor {

	private static final String RUN_URL_PREFIX = "/api";

	private static Logger logger = LoggerFactory.getLogger(ScriptExecutor.class);

	private static ObjectMapper objectMapper = new ObjectMapper();

	@Resource
	private GroovyScriptEngine groovyScriptEngine;

	@Resource
	private SqlHolder sqlHolder;

	@RequestMapping(RUN_URL_PREFIX + "/**")
	public Object run(HttpServletRequest request) {

		String scriptPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
		String scriptFile = scriptPath.replaceFirst(RUN_URL_PREFIX, "").substring(1) + ".groovy";

		// Parse Params
		Map<String, Object> params = parseParams(request);

		Binding binding = new Binding();
		binding.setVariable("params", params);
		binding.setVariable("sqlHolder", sqlHolder);

		try {
			Object result = groovyScriptEngine.run(scriptFile, binding);
			return result;

		} catch (Exception e) {
			logger.error("Script:{} Error:", scriptPath, e);
			Map<String, Object> errorResult = new HashMap<String, Object>();
			errorResult.put("status", 500);
			errorResult.put("exception", e);
			return errorResult;
		} finally {

		}

	}

	private Map<String, Object> parseParams(HttpServletRequest request) {
		Map<String, Object> paramMap = new LinkedHashMap<String, Object>();
		for (String paramName : request.getParameterMap().keySet()) {
			paramMap.put(paramName, request.getParameter(paramName));
		}
		String requestBodyContent = null;
		try {
			requestBodyContent = IOUtils.toString(request.getReader());
			if (StringUtils.hasLength(requestBodyContent)) {
				@SuppressWarnings("unchecked")
				Map<String, Object> bodyMap = objectMapper.readValue(requestBodyContent, Map.class);
				paramMap.putAll(bodyMap);
			}
		} catch (Exception e) {
			logger.error("Error Parse Request Params" + requestBodyContent, e);
			throw new RuntimeException("Error Parse Request Params", e);
		}
		return paramMap;
	}
}
